﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Xml.Linq;
using System.Text.RegularExpressions;
using Lucene.Net.Store;
using Lucene.Net.Index;
using System.Net;
using System.Text;
using mshtml;
using Lucene.Net.Documents;
using log4net;
using System.IO;
using Lucene.Net.Analysis.PanGu;
using PanGu;
using Lucene.Net.Analysis;
using Lucene.Net.Search;
using System.Data.SqlClient;
using System.Data;

public partial class test_索引文章 : System.Web.UI.Page
{
    private ILog logger = LogManager.GetLogger(typeof(test_索引文章));
    protected void Page_Load(object sender, EventArgs e)
    {

    }
    protected void Button1_Click(object sender, EventArgs e)
    {
        logger.Debug("开始");
        string indexPath = "c:/index";
        FSDirectory directory = FSDirectory.Open(new DirectoryInfo(indexPath), new NativeFSLockFactory());
        bool isUpdate = IndexReader.IndexExists(directory);
        if (isUpdate)
        {
            //如果索引目录被锁定（比如索引过程中程序异常退出），则首先解锁
            if (IndexWriter.IsLocked(directory))
            {
                IndexWriter.Unlock(directory);
            }
        }

        IndexWriter writer = new IndexWriter(directory, new PanGuAnalyzer(), !isUpdate, Lucene.Net.Index.IndexWriter.MaxFieldLength.UNLIMITED);
        //WebClient wc = new WebClient();
        
        //wc.Encoding = Encoding.UTF8;//否则下载的是乱码
        int maxId = GetMaxId();
        for (int i = 1; i <= maxId; i++)
        {
            //string url = "http://localhost:10742/web/detail.aspx?id=" + i;
            //HttpWebRequest webrequest = (HttpWebRequest)WebRequest.Create(url);

            //webrequest.CookieContainer = new CookieContainer();
            
            //string html = wc.DownloadString(url);
            
            //HTMLDocumentClass对页面html进行解析的类，IE就是用它进行解析的
            //HTMLDocumentClass doc = new HTMLDocumentClass();
            //doc.designMode = "on"; //不让解析引擎去尝试运行javascript
            
            ////html为要解析的代码
            //doc.IHTMLDocument2_write(html);
            //doc.close();

            //string title = doc.title;
            //string body = doc.body.innerText.Substring(90);//去掉标签，只取其中的text内容
            string title;
            string body;
            DataRow dr = getSearch(i);
            if (dr == null)
            {
                title = "";
                body = "";
            }
            else
            {
                title = dr[1].ToString(); ;
                body = dr[0].ToString() + dr[1].ToString() + dr[2].ToString() + dr[3].ToString() + dr[4].ToString();
            }
            //为避免重复索引，所以先删除number=i的记录，再重新添加
            writer.DeleteDocuments(new Term("number", i.ToString()));

            Document document = new Document();
            //只有对需要全文检索的字段才ANALYZED（分词）
            document.Add(new Field("number", i.ToString(), Field.Store.YES, Field.Index.NOT_ANALYZED));
            document.Add(new Field("title", title, Field.Store.YES, Field.Index.ANALYZED, Lucene.Net.Documents.Field.TermVector.WITH_POSITIONS_OFFSETS));
            document.Add(new Field("body", body, Field.Store.YES, Field.Index.ANALYZED, Lucene.Net.Documents.Field.TermVector.WITH_POSITIONS_OFFSETS));
            writer.AddDocument(document);
            logger.Debug("索引" + i + "完毕");
        }
        writer.Close();
        directory.Close();//不要忘了Close，否则索引结果搜不到
        logger.Debug("全部索引完毕");
        logger.Debug("结束");

    }

    protected void Button2_Click(object sender, EventArgs e)
    {
        string indexPath = "c:/index";
        string kw = TextBox1.Text;
        //保存索引文件到名字为indexPath文件夹中（FSDirectory：保存索引文件到文件中）
        FSDirectory directory = FSDirectory.Open(new DirectoryInfo(indexPath), new NoLockFactory());
        //IndexReader对索引文件进行读取的类
        IndexReader reader = IndexReader.Open(directory, true);
        //IndexSearcher进行搜索的类，构造函数中传递IndexReader类实体
        IndexSearcher searcher = new IndexSearcher(reader);
        //PhraseQuery对多个关键词进行搜索
        PhraseQuery query = new PhraseQuery();

        //todo:把用户输入的关键词进行拆词

        foreach (string word in SplitWord(TextBox1.Text))//先用空格，让用户去分词，空格分隔的就是词“计算机 专业”
        {
            //body中含有word关键词
            query.Add(new Term("body", word));
        }
        //query.Add(new Term("body","计算机"));
        //query.Add(new Term("body", "专业"));
        //设置关键词之间的最大距离
        query.SetSlop(100);
        //结果收集器，设置为最大收集为1000
        TopScoreDocCollector collector = TopScoreDocCollector.create(1000, true);
        //通过search方法根据query条件进行搜索
        searcher.Search(query, null, collector);
        ScoreDoc[] docs = collector.TopDocs(0, collector.GetTotalHits()).scoreDocs;
        List<MODEL.LostAndFound> listResult = new List<MODEL.LostAndFound>();
        for (int i = 0; i < docs.Length; i++)
        {
            int docId = docs[i].doc;//取到文档的编号（主键，这个是Lucene .net分配的）
            //检索结果中只有文档的id，如果要取Document，则需要Doc再去取
            //降低内容占用
            Document doc = searcher.Doc(docId);//根据id找Document
            string number = doc.Get("number");
            string title = doc.Get("title");
            string body = doc.Get("body");

            MODEL.LostAndFound result = new MODEL.LostAndFound();
            result.LId = Convert.ToInt32(number);
            result.GoodsName = title;

            
            result.Feature = Preview(body, TextBox1.Text);

            listResult.Add(result);
        }
        repeaterResult.DataSource = listResult;
        repeaterResult.DataBind();
    }

    #region 字体高亮
    /// <summary>
    /// 字体高亮
    /// </summary>
    /// <param name="body"></param>
    /// <param name="keyword"></param>
    /// <returns></returns>
    private static string Preview(string body, string keyword)
    {
        //创建HTMLFormatter,参数为高亮单词的前后缀 
        PanGu.HighLight.SimpleHTMLFormatter simpleHTMLFormatter =
               new PanGu.HighLight.SimpleHTMLFormatter("<font color=\"red\">", "</font>");
        //创建 Highlighter ，输入HTMLFormatter 和 盘古分词对象Semgent 
        PanGu.HighLight.Highlighter highlighter =
                        new PanGu.HighLight.Highlighter(simpleHTMLFormatter,
                        new Segment());
        //设置每个摘要段的字符数 
        highlighter.FragmentSize = 60;
        //获取最匹配的摘要段 
        String bodyPreview = highlighter.GetBestFragment(keyword, body);
        return bodyPreview;
    } 
    #endregion

    #region 读取rss的xml文件  获得最大id号
    /// <summary>
    /// 读取rss的xml文件  获得最大id号
    /// </summary>
    /// <returns></returns>
    public int GetMaxId()
    {
        XDocument xdoc = XDocument.Load("http://localhost:10742/web/rss.aspx");
        XElement channel = xdoc.Root.Element("channel");
        XElement firstItem = channel.Elements("item").First();
        XElement link = firstItem.Element("link");
        Match m = Regex.Match(link.Value, @"detail\.aspx\?id=(\d+)");
        int maxid = Convert.ToInt32(m.Groups[1].Value);//正则表达式中的数组的下标起始为1
        return maxid;
    }
    #endregion

    #region 盘古分词 返回一个字符串数组
    /// <summary>
    /// 盘古分词 返回一个字符串数组
    /// </summary>
    /// <param name="str"></param>
    /// <returns></returns>
    public static string[] SplitWord(string str)
    {
        List<string> list = new List<string>();
        Analyzer analyzer = new PanGuAnalyzer();
        TokenStream tokenStream = analyzer.TokenStream("", new StringReader(str));
        Lucene.Net.Analysis.Token token = null;
        while ((token = tokenStream.Next()) != null)
        {
            list.Add(token.TermText());
        }
        return list.ToArray();
    } 
    #endregion

    #region 读取数据库的内容 根据LId
    /// <summary>
    /// 读取数据库的内容 根据LId
    /// </summary>
    /// <param name="lid"></param>
    /// <returns></returns>
    public DataRow getSearch(int lid)
    {
        DAL.DbHelperSQL dbhelper = new DAL.DbHelperSQL();
        string sql = "select LostProperty,GoodsName,Feature,Address,UName from LostAndFound laf join Users u on laf.UserId=u.UId where LId=@LId and IsDel=0;";
        SqlParameter[] paras = { 
                                 new SqlParameter("@LId",lid)
                               };
        DataRow dr = dbhelper.GetDataRow(sql, paras);
        if (dr == null)
        {
            return null;
        }
        return dr;
    } 
    #endregion

    
}